#!/usr/bin/python3
# -*- coding: utf-8 -*-

from configparser import ConfigParser
from json import dumps
from os import path
from sys import exit
from time import sleep

from modules.api.base_translation import BaseTranslation
from modules.api.tencent.tencentcloud.common import credential
from modules.api.tencent.tencentcloud.common.exception.tencent_cloud_sdk_exception import (
    TencentCloudSDKException,
)
from modules.api.tencent.tencentcloud.common.profile.client_profile import ClientProfile
from modules.api.tencent.tencentcloud.common.profile.http_profile import HttpProfile
from modules.api.tencent.tencentcloud.tmt.v20180321 import models, tmt_client
from modules.utils import MY_ERROR_CODES, get_file_encoding, print_err, print_warn

# 所有支持的语种字典
_TENCENT_COMMON_LANGS = [
    'auto',
    'zh',
    'zh-TW',
    'en',
    'ja',
    'ru',
    'fr',
    'ko',
    'es',
    'it',
    'de',
    'tr',
    'pt',
    'vi',
    'id',
    'th',
    'ms',
    'ar',
    'hi',
]

# 源语种字典
_TENCENT_FROM_LANGS = {
    '1': {'n': '自动检测（推荐）', 'c': 'auto'},
    '2': {'n': '简体中文', 'c': 'zh'},
    '3': {'n': '繁体中文', 'c': 'zh-TW'},
    '4': {'n': '英语', 'c': 'en'},
    '5': {'n': '日语', 'c': 'ja'},
    '6': {'n': '俄语', 'c': 'ru'},
    '7': {'n': '法语', 'c': 'fr'},
    '8': {'n': '韩语', 'c': 'ko'},
    '9': {'n': '西班牙语', 'c': 'es'},
    '10': {'n': '意大利语', 'c': 'it'},
    '11': {'n': '德语', 'c': 'de'},
    '12': {'n': '土耳其语', 'c': 'tr'},
    '13': {'n': '葡萄牙语', 'c': 'pt'},
    '14': {'n': '越南语', 'c': 'vi'},
    '15': {'n': '印尼语', 'c': 'id'},
    '16': {'n': '泰语', 'c': 'th'},
    '17': {'n': '马来西亚语', 'c': 'ms'},
    '18': {'n': '阿拉伯语', 'c': 'ar'},
    '19': {'n': '印地语', 'c': 'hi'},
}

# 常用目标语种字典
_TENCENT_TO_LANGS = {
    '1': {'n': '简体中文', 'c': 'zh'},
    '2': {'n': '英语', 'c': 'en'},
    '3': {'n': '日语', 'c': 'ja'},
}

# 错误码表
_TENCENT_ERROR_CODES = {
    'FailedOperation.NoFreeAmount': '本月免费额度已用完！如需继续使用您可以在机器翻译控制台升级为付费使用。',
    'FailedOperation.ServiceIsolate': '账号因为欠费停止服务！请在腾讯云账户充值。',
    'FailedOperation.UserNotRegistered': '服务未开通！请在腾讯云官网机器翻译控制台开通服务。',
    'InternalError': '内部错误！',
    'InternalError.BackendTimeout': '后台服务超时！请稍后重试。',
    'InternalError.ErrorUnknown': '未知错误！请稍后重试。',
    'InternalError.RequestFailed': '参数错误！请检查参数。',
    'LimitExceeded': '超过配额限制！',
    'MissingParameter': '缺少参数错误！请检查参数。',
    'UnauthorizedOperation.ActionNotFound': '请填写正确的Action字段名称！',
    'UnsupportedOperation': '操作不支持！',
    'UnsupportedOperation.TextTooLong': '单次请求text超过长度限制！请保证单次请求⻓度低于2000。',
    'UnsupportedOperation.UnSupportedTargetLanguage': '不支持的目标语言！请参照语言列表。',
    'UnsupportedOperation.UnsupportedLanguage': '不支持的语言！请参照语言列表。',
    'UnsupportedOperation.UnsupportedSourceLanguage': '不支持的源语言！请参照语言列表。',
}


class TencentTranslation(BaseTranslation):
    '''
    腾讯翻译君API
    '''

    def __init__(self, section: str):

        BaseTranslation.__init__(self, section)
        self.section = section

        self._secret_id = ''
        self._secret_key = ''
        if self._conf and len(self._conf) > 0:
            self._secret_id = self._conf['secretId']
            self._secret_key = self._conf['secretKey']
        if self._secret_id == '' or self._secret_key == '':
            print_err('翻译API启用失败，请在api_keys.ini中配置secretId和ecretKey！')
            exit(0)

        self._get_config()

    def translate(
        self, source_txt: str, to_lang: str, from_lang='auto', times=0
    ) -> str:
        '''
        开始翻译

        - source_txt: 输入文本
        - to_lang: 目标语种
        - from_lang: 源语种
        - times: 重试次数
        '''

        # 当源语言不在受支持的语种范围内时，强制将源语言设置为auto，确保翻译能正常进行
        if not from_lang in _TENCENT_COMMON_LANGS:
            from_lang = 'auto'
            print_warn('源语言不在受支持的语种范围内，已强制重置为“自动检测”！')

        # 当源语言不在受支持的语种范围内时，强制将源语言设置为zh，确保翻译能正常进行
        if not to_lang in _TENCENT_COMMON_LANGS:
            to_lang = 'zh'
            print_warn('目标语言不在受支持的语种范围内，已强制重置为“简体中文”！')

        if to_lang == from_lang:
            print_warn('目标语种和源语种相同。')
            return source_txt

        # 原文本长度超过上限
        if len(source_txt) > self._max_char:
            print_err(MY_ERROR_CODES['ERR_10002'])
            return 'ERR_10002'

        # 重试次数大于3次依然未成功，则返回错误代码
        if times > 3:
            return 'ERR_10001'
        times += 1

        target = ''
        try:
            cred = credential.Credential(self._secret_id, self._secret_key)
            httpProfile = HttpProfile()
            httpProfile.endpoint = "tmt.tencentcloudapi.com"

            clientProfile = ClientProfile()
            clientProfile.httpProfile = httpProfile
            client = tmt_client.TmtClient(cred, "ap-shanghai", clientProfile)

            req = models.TextTranslateRequest()

            _params = {
                'SourceText': source_txt,
                'Source': from_lang,
                'Target': to_lang,
                'ProjectId': 0,
            }
            params = dumps(_params)
            req.from_json_string(params)

            resp = client.TextTranslate(req)
            target = resp.TargetText

        except TencentCloudSDKException as err:
            if err.get_code() in [
                'InternalError.BackendTimeout',
                'InternalError.ErrorUnknown',
            ]:
                print_warn(err.get_message())
                sleep(3)
                return self.translate(source_txt, to_lang, from_lang, times)

            print_err(err.get_message())
            target = 'ERR_10001'

        return target

    def _get_config(self):
        '''
        获取配置
        '''

        config_path = path.join(
            path.abspath('.'), 'modules', 'api', 'tencent', 'config.ini'
        )
        if not path.isfile(config_path):
            return

        conf = ConfigParser()  # 调用读取配置模块中的类
        conf.optionxform = lambda option: option
        conf.read(config_path, encoding=get_file_encoding(config_path))

        self._rate = conf.getint(self.section, 'rate')
        if self._rate < 1:
            self._rate = 1
        self._max_char = conf.getint(self.section, 'max_char')
        if self._max_char < 50:
            self._max_char = 2000

    def get_from_langs(self) -> dict:
        '''
        获取源语种字典
        '''
        return _TENCENT_FROM_LANGS

    def get_to_langs(self) -> dict:
        '''
        获取目标语种字典
        '''
        return _TENCENT_TO_LANGS
